﻿using System;
using MathNet.Numerics.LinearAlgebra;

namespace GridRayTracer.Primitives
{
  [Serializable]
  public class Sphere : SceneObject
  {
    public Sphere() 
    {
      Radius = 1.0;
    }
    
    public override HitResult HitTest(Ray ray)
    {      
      // Convert ray into local coordinates
      var start = ray.Start - Translation;
      var dir = (RotationInverted * ray.Direction.ToColumnMatrix()).GetColumnVector(0);
           
      // Solve t * t + 2 * b * t + c = 0 equation for the intersection point
      double b = start.ScalarMultiply(dir);
      double c = start.SquaredNorm() - Radius * Radius;
      double D = b * b - c;
      if (D < 0) 
        return null;
      double t = -b - Math.Sqrt(D);
      if (t < 0)
        t = -t - 2 * b;
      if (t < 0)
        return null;
      
      // Compute hit info and convert into world coordinates
      var hitPoint = start + dir.Scale(t);
      var normal = hitPoint.Normalize();
      hitPoint = (Rotation * hitPoint.ToColumnMatrix()).GetColumnVector(0) + Translation;
      normal = (Rotation * normal.ToColumnMatrix()).GetColumnVector(0);      
      return new HitResult(ray, this, hitPoint, normal);      
    }
    
    public double Radius 
    {
      get;
      set;      
    }    
  }
}
